package self.xine.basic.thread.communication;

import self.xine.basic.thread.entity.SharedObject;

/**
 * 多线程间的通信，是通过共用的对象来作为桥梁实现的
 * 	
 *  而线程不安全，是指其在单线程内运行无误，
 *  	但在多线程中执行时由于未进行控制，极易引发共享数据错误问题 * 
 * 
 * @author xine
 * @date 2018年9月8日
 */
public class ThreadWait{
		
	public static void main(String[] args) {
		SharedObject sharedObject = new SharedObject();
		
		Thread t1 = new Thread(new MyAddRunnable(sharedObject),"线程1");
		Thread t2 = new Thread(new MySubRunnable(sharedObject),"线程2");

		t1.start();
		t2.start();
		
		long timeStart = System.currentTimeMillis();
		while(System.currentTimeMillis() - timeStart < 20000) {
			System.out.println(t1.getName() + " " + t1.getState().name() + " --- " + t2.getName() + " " + t2.getState().name());
		}
		sharedObject.setTerminated(true);
				
		try {
			t1.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		try {
			t2.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		System.out.println(sharedObject.getCount());
		
	}

}

class MySubRunnable implements Runnable {
	private SharedObject sharedObject;
	
	public MySubRunnable( SharedObject sharedObject) {
		this.sharedObject = sharedObject;		
	}
	
	@Override
	public void run() {
		synchronized (sharedObject) {
			while(!sharedObject.isTerminated()) {
				if(sharedObject.getCount() < 5) {
					try {
						sharedObject.wait();					
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}			

				sharedObject.sub(1);						
				System.out.println(Thread.currentThread().getName() + " : " + sharedObject.getCount());
				sharedObject.notifyAll();
				
			}
		}		
	}
}

class MyAddRunnable implements Runnable {
	private SharedObject sharedObject;
		
	public MyAddRunnable(SharedObject sharedObject) {
		this.sharedObject = sharedObject;		
	}
	
	@Override
	public void run() {
		synchronized (sharedObject) {
			while(!sharedObject.isTerminated()) {
				if(sharedObject.getCount() > 5) {
					try {
						sharedObject.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				
				sharedObject.add(1);			
				System.out.println(Thread.currentThread().getName() + " : " + sharedObject.getCount());
				
				sharedObject.notifyAll();
			}
		}		
	}
}
